﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Net;
using System.Text.RegularExpressions;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using GalaSoft.MvvmLight.Command;
using GalaSoft.MvvmLight.Messaging;
using JustinAngel.Neurons.Framework;
using JustinAngel.Neurons.Framework.Messages;
using JustinAngel.Neurons.Pages.Main;
using JustinAngel.Neurons.Services;
using Microsoft.Phone.Shell;
using Microsoft.SilverlightMediaFramework.Core;
using Microsoft.SilverlightMediaFramework.Core.Media;
using Microsoft.SilverlightMediaFramework.Plugins.Primitives;
using JustinAngel.Neurons.Framework.Helpers;

namespace JustinAngel.Neurons.Pages.VideoPlayer
{
    /// <summary>
    /// This class has been heavily modified to avoid sharing Justin's YT developer key.
    /// As such only low-res videos will be supported in the open source version of Neurons. 
    /// Sorry. 
    /// </summary>
    public class VideoPlayerViewModel : VViewModelBase
    {
        public VideoPlayerViewModel()
        {
            IoC.BuildUp(this);

            MessengerInstance.Register<ApplicationDeactivatedMessage>(this, OnApplicationDeactivatedMessage);
            MessengerInstance.Register<ApplicationActivatedMessage>(this, msg => CheckForApplicationActivated());
            CheckForApplicationActivated();
        }

        private void CheckForApplicationActivated()
        {
            if (PhoneApplicationService.Current.State.ContainsKey("VideoPlayerViewModel.Data"))
            {
                Data = PhoneApplicationService.Current.State["VideoPlayerViewModel.Data"];
                PhoneApplicationService.Current.State.Remove("VideoPlayerViewModel.Data");
            }
            if (PhoneApplicationService.Current.State.ContainsKey("VideoPlayerViewModel.CurrentPlaybackPosition"))
            {
                CurrentPlaybackPosition = (TimeSpan) PhoneApplicationService.Current.State["VideoPlayerViewModel.CurrentPlaybackPosition"];
                PhoneApplicationService.Current.State.Remove("VideoPlayerViewModel.CurrentPlaybackPosition");
            }
        }

        private void OnApplicationDeactivatedMessage(ApplicationDeactivatedMessage obj)
        {
            PhoneApplicationService.Current.State["VideoPlayerViewModel.Data"] = Data;
        }


        public override void OnDataSet()
        {
            IsLoading = true;

            PlayerSourceUri = null;
            CurrentPlaybackPosition = TimeSpan.FromMilliseconds(0);

            Deployment.Current.Dispatcher.BeginInvoke(() => PlayVideoFromRawDataAndWriteToZuneHub());
        }

        [Dependency]
        public IWebRequestMaker WebRequestMaker { get; set; }

        private const string YouTubeLowRestGetter =
            "http://pipes.yahoo.com/pipes/pipe.run?_id=0fe7153353e296af936a1e6fb0ba2a0b&_render=json&videoid=";

        private void PlayVideoFromRawDataAndWriteToZuneHub()
        {
            
            WebRequestMaker.StartWithCredentialsAndTimeout(
                YouTubeLowRestGetter + RealData.YouTubeID,
                TimeSpan.FromSeconds(30),
                SetSourceBasedOnYouTubeAPI,
                OnYouTubeFailure);

            if (!RealData.IsRestoreFromMediaTile)
                ZuneMediaHubIntegrationService.PlayingVideo(RealData);
        }
        
        private void SetSourceBasedOnYouTubeAPI(Stream response)
        {
            var strResponse = response.ReadToEnd();
            if (string.IsNullOrEmpty(strResponse))
            {
                OnYouTubeFailure();
                return;
            }

            strResponse = strResponse.Replace(@"\/", "/");
            Regex r = new Regex("rtsp://(.*)3gp", RegexOptions.Singleline);
            var match = r.Match(strResponse);

            Uri youTubeUri;
            if (!Uri.TryCreate(match.Value, UriKind.Absolute, out youTubeUri))
            {
                OnYouTubeFailure();
                return;
            }


            if (NetworkStatusProvider.IsConnectedToWifi)
                BeginInvokeOnUIThread(() => PlayerSourceUri = youTubeUri);
            else
                BeginInvokeOnUIThread(() => PlayerSourceUri = youTubeUri);

        }

        private void OnYouTubeFailure()
        {
            DialogService.ShowMessageBox("Please contact app developer.",
                                         "Video play failure",
                                        MessageBoxButton.OK
            );
        }

        [Dependency]
        public IDialogService DialogService { get; set; }

        [Dependency]
        public INetworkStatusProvider NetworkStatusProvider { get; set; }


        public VideoItemViewModel RealData { get { return (VideoItemViewModel)Data; } }

        private bool _isLoading;
        public bool IsLoading
        {
            get { return _isLoading; }
            set
            {
                _isLoading = value;
                RaisePropertyChangedAndUpdateVSM(() => IsLoading, value);
            }
        }

        private Uri _playerSourceUri;
        public Uri PlayerSourceUri
        {
            get { return _playerSourceUri; }
            set
            {
                if (IsInEmulator)
                {
                        if (RealData.ExternalLink.OriginalString == "http://www.youtube.com/watch?v=6Tn3-eB_hcQ")
                        {
                            _playerSourceUri = new Uri("/stephanfry.wmv", UriKind.Relative);
                        }
                        else if (RealData.ExternalLink.OriginalString == "http://www.youtube.com/watch?v=GlUS6KE67Vs&feature=youtube_gdata")
                        {
                            _playerSourceUri = new Uri("/MelindaGates.wmv", UriKind.Relative);
                        }
                        else
                        {
                            _playerSourceUri = new Uri("http://cdn2.newsy.com/files/3613_wmv_12880484305.wmv");
                        }
                }
                else
                {
                    _playerSourceUri = value;
                }
                RaisePropertyChanged(() => PlayerSourceUri);
                RaisePropertyChanged(() => Playlist);
            }
        }

        public ObservableCollection<PlaylistItem> Playlist
        {
            get
            {
                return new ObservableCollection<PlaylistItem>()
                       {
                           new PlaylistItem()
                               {
                                   Title = RealData == null ? string.Empty : RealData.Title,
                                   MediaSource = PlayerSourceUri
                               }
                       };
            }
        }

        public ICommand PlayStateChangedCommand
        {
            get
            {
                return new RelayCommand<CustomEventArgs<MediaPluginState>>(e =>
                {
                    if (e.Value == MediaPluginState.Playing)
                    {
                        IsLoading = false;

                        if (CurrentPlaybackPosition.TotalMilliseconds != 0)
                        {
                            MessengerInstance.Send(new SetVideoPlayerCurrentPlaybackPositionMessage(CurrentPlaybackPosition));
                            CurrentPlaybackPosition = TimeSpan.FromMilliseconds(0);
                        }
                    }
                    if (e.Value == MediaPluginState.Buffering)
                    {
                        IsLoading = true;
                    }
                });
            }   
        }

        [Dependency]
        public IZuneMediaHubIntegrationService ZuneMediaHubIntegrationService { get; set; }


        public TimeSpan CurrentPlaybackPosition { get; set; }
    }

    public class SetVideoPlayerCurrentPlaybackPositionMessage : GenericMessage<TimeSpan>
    {
        public SetVideoPlayerCurrentPlaybackPositionMessage(TimeSpan content) : base(content)
        {
        }
    }
}
